package generator

import (
	"fmt"
	"io/ioutil"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/validation"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"path/filepath"
	"strings"
	"v8s-controller/internal/configuration"
)

type (
	ImagePullSecretsGenerator struct {
		configs map[string][]byte
	}
)

var (
	SecretMeta = metav1.TypeMeta{
		Kind:       "Secret",
		APIVersion: "v1",
	}
)

func NewImagePullSecretsGenerator(properties configuration.GeneratorProperties) *ImagePullSecretsGenerator {
	configs := map[string][]byte{}

	for _, path := range properties.ImagePullSecretFiles {
		data, err := ioutil.ReadFile(path)
		if err != nil {
			panic(fmt.Sprintf("failed to read file '%s': %s", path, err))
		}

		_, file := filepath.Split(path)
		file = strings.TrimSuffix(file, filepath.Ext(file))

		var nameErr error
		for _, err := range validation.NameIsDNSSubdomain(file, false) {
			if nameErr == nil {
				nameErr = fmt.Errorf(err)
				continue
			}

			nameErr = fmt.Errorf("%s: %w", err, nameErr)
		}
		if nameErr != nil {
			panic(fmt.Sprintf("invalid file '%s' name: %s", file, nameErr))
		}

		configs[file] = data
	}

	return &ImagePullSecretsGenerator{
		configs: configs,
	}
}

func (g *ImagePullSecretsGenerator) Generate() []*corev1.Secret {
	secrets := make([]*corev1.Secret, 0, len(g.configs))

	for name, config := range g.configs {
		secrets = append(secrets, &corev1.Secret{
			TypeMeta: SecretMeta,
			ObjectMeta: metav1.ObjectMeta{
				Name: name,
			},
			Data:       map[string][]byte{corev1.DockerConfigJsonKey: config},
			StringData: nil,
			Type:       corev1.SecretTypeDockerConfigJson,
		})
	}

	return secrets
}
